package com.yzcrm.erp.psi.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Aop;
import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.core.paragetter.Para;
import com.jfinal.kit.Kv;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.SqlPara;
import com.jfinal.plugin.activerecord.tx.TxSerializable;
import com.yzcrm.common.config.exception.YzcrmException;
import com.yzcrm.common.config.paragetter.BasePageRequest;
import com.yzcrm.common.constant.BaseConstant;
import com.yzcrm.erp.admin.entity.AdminField;
import com.yzcrm.erp.admin.entity.AdminScene;
import com.yzcrm.erp.admin.service.*;
import com.yzcrm.erp.crm.common.CheckStatusEnum;
import com.yzcrm.erp.crm.common.CrmEnum;
import com.yzcrm.erp.crm.entity.CrmProduct;
import com.yzcrm.erp.crm.common.FormTypeEnum;
import com.yzcrm.erp.crm.service.CrmRecordService;
import com.yzcrm.erp.psi.common.PsiUtil;
import com.yzcrm.erp.psi.entity.PsiEnterLeaveStock;
import com.yzcrm.erp.psi.entity.PsiEnterLeaveStockDetail;
import com.yzcrm.erp.psi.entity.PsiProductSupplier;
import com.yzcrm.erp.psi.entity.PsiStockpile;
import com.yzcrm.utils.AuthUtil;
import com.yzcrm.utils.BaseUtil;
import com.yzcrm.utils.ParamsUtil;
import com.yzcrm.utils.R;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author jiang.xue
 */
public class PsiEnterLeaveStockService {

    @Inject
    private CrmRecordService crmRecordService;

    @Inject
    private AdminFieldService adminFieldService;

    @Inject
    private AdminSceneService adminSceneService;

    @Inject
    private AdminExamineRecordService examineRecordService;

    /**
     * 出入库
     * @param jsonObject
     * @return
     */
    @Before(TxSerializable.class)
    public R addOrUpdate(JSONObject jsonObject) {

        Log.getLog(getClass()).info(jsonObject.toString());

        PsiEnterLeaveStock psiEnterLeaveStock = jsonObject.getObject("entity", PsiEnterLeaveStock.class);
        if(ObjectUtil.isNull(psiEnterLeaveStock)) {
            return R.error("参数不正确");
        }

        // 获取label
        CrmEnum crmEnum = CrmEnum.parse(psiEnterLeaveStock.getLabel());
        String realm = crmEnum.getName();
        if(ObjectUtil.isNull(realm)) {
            return R.error("label不存在");
        }


        JSONArray jsonArrayProducts = jsonObject.getJSONArray("products");
        if (ObjectUtil.isNull(jsonArrayProducts) || jsonArrayProducts.size() == 0) {
            return R.error("请添加出入库的商品");
        }

//        // 审核状态设置
//        if (ObjectUtil.isNotNull(psiEnterLeaveStock.getCheckStatus() )
//                && psiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_DRAFT.getType()) {
//        } else {
//            psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_WAIT.getType());
//        }

        String batchId = StrUtil.isNotEmpty(psiEnterLeaveStock.getBatchId()) ? psiEnterLeaveStock.getBatchId() : IdUtil.simpleUUID();
        adminFieldService.save(jsonObject.getJSONArray("field"), batchId);
        boolean flag;
        if(psiEnterLeaveStock.getElsId() != null){
            // 更新

            crmRecordService.updateRecord(jsonObject.getJSONArray("field"), batchId);

            PsiEnterLeaveStock oldPsiEnterLeaveStock = PsiEnterLeaveStock.dao.findById(psiEnterLeaveStock.getElsId());
            if(ObjectUtil.isNull(oldPsiEnterLeaveStock)) {
                throw new YzcrmException("要修改的出入库信息不存在，无法编辑");
            }

            // 审核拒绝，已撤回，草稿能够修改
            if(oldPsiEnterLeaveStock.getCheckStatus() != CheckStatusEnum.CHECK_STATUS_REJECTED.getType()
                    && oldPsiEnterLeaveStock.getCheckStatus() != CheckStatusEnum.CHECK_STATUS_UNDO.getType()
                    && oldPsiEnterLeaveStock.getCheckStatus() != CheckStatusEnum.CHECK_STATUS_DRAFT.getType()) {
                CheckStatusEnum checkStatusEnum = CheckStatusEnum.parse(oldPsiEnterLeaveStock.getCheckStatus());
                throw new YzcrmException("出入库信息"+checkStatusEnum.getRemarks()+"，无法编辑，请先撤回再编辑");
            }

            // 更新审核信 息
            Map<String, Integer> map = examineRecordService.saveExamineRecord(psiEnterLeaveStock.getLabel(), jsonObject.getLong("checkUserId"), oldPsiEnterLeaveStock.getOwnerUserId(),
                    oldPsiEnterLeaveStock.getExamineRecordId(), psiEnterLeaveStock.getCheckStatus());
            if (map.get("status") == 0) {
                throw new YzcrmException("没有启动的审核步骤，不能添加！");
            } else {
                psiEnterLeaveStock.setExamineRecordId(map.get("id"));
            }

            if (psiEnterLeaveStock.getCheckStatus() != null && psiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_DRAFT.getType()) {
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_DRAFT.getType());
            } else if(psiEnterLeaveStock.getCheckStatus() != null && psiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_OK.getType()){
                //批量导入时
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_OK.getType());
            } else{
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_WAIT.getType());
            }

            psiEnterLeaveStock.setUpdateTime(DateUtil.date());
            psiEnterLeaveStock.setUpdateUserId(BaseUtil.getUser().getUserId());
            flag = psiEnterLeaveStock.update();

            crmRecordService.updateRecord(oldPsiEnterLeaveStock, psiEnterLeaveStock, crmEnum);

            // 在审批后增加出入库商品在库数
            // 更新出入库商品详情,删除原有的商品明细
            Integer count = Db.update(Db.getSql("psi.enterLeaveStockDetail.deleteByElsId"), psiEnterLeaveStock.getElsId());
            if (count <= 0) {
                throw new YzcrmException("出入库失败，请刷新页面重新尝试操作");
            }

            // 增加新商品明细
            for (int i = 0; i < jsonArrayProducts.size(); i++) {

                JSONObject jsonObjectProduct = jsonArrayProducts.getJSONObject(i);
                PsiEnterLeaveStockDetail enterLeaveStockDetail = jsonObjectProduct.toJavaObject(PsiEnterLeaveStockDetail.class);

                CrmProduct crmProduct = CrmProduct.dao.findById(enterLeaveStockDetail.getProductId());
                if(ObjectUtil.isNull(crmProduct)) {
                    throw new YzcrmException("出入库失败，产品不存在");
                }
                if(PsiUtil.isEnterStock(crmEnum.getType()) && crmProduct.getUpcCodeUniqueFlag() == 1 && ObjectUtil.isEmpty(enterLeaveStockDetail.getUpcCode())) {
                    throw new YzcrmException("产品" + crmProduct.getName() + "的序列号不能为空");
                }

                enterLeaveStockDetail.setElsdetailId(null);
                enterLeaveStockDetail.setElsId(psiEnterLeaveStock.getElsId());
                enterLeaveStockDetail.setCreateTime(DateUtil.date());
                enterLeaveStockDetail.setCreateUserId(BaseUtil.getUser().getUserId());
                enterLeaveStockDetail.setUpdateTime(DateUtil.date());
                boolean result = enterLeaveStockDetail.save();
                if(!result) {
                    throw new YzcrmException("产品详细保存失败");
                }
            }


        }else{
            // 增加

            psiEnterLeaveStock.setCreateTime(DateUtil.date());
            psiEnterLeaveStock.setUpdateTime(DateUtil.date());
            psiEnterLeaveStock.setCreateUserId(BaseUtil.getUser().getUserId());
            psiEnterLeaveStock.setBatchId(batchId);
//            psiEnterLeaveStock.setCheckStatus(0); // 0 或者5
            psiEnterLeaveStock.setStatus(1);
            psiEnterLeaveStock.setOwnerUserId(BaseUtil.getUser().getUserId());

            // 增加审核
            Map<String, Integer> map = examineRecordService.saveExamineRecord(psiEnterLeaveStock.getLabel(), jsonObject.getLong("checkUserId"), psiEnterLeaveStock.getOwnerUserId(), null, psiEnterLeaveStock.getCheckStatus());
            if (map.get("status") == 0) {
                throw new YzcrmException("没有启动的审核步骤，不能添加！");

            } else {
                psiEnterLeaveStock.setExamineRecordId(map.get("id"));
            }

            if (psiEnterLeaveStock.getCheckStatus() != null && psiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_DRAFT.getType()) {
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_DRAFT.getType());
            } else if(psiEnterLeaveStock.getCheckStatus() != null && psiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_OK.getType()){
                //批量导入时
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_OK.getType());
            } else{
                psiEnterLeaveStock.setCheckStatus(CheckStatusEnum.CHECK_STATUS_WAIT.getType());
            }

            flag = psiEnterLeaveStock.save();
            crmRecordService.addRecord(psiEnterLeaveStock.getElsId(), crmEnum);

            // 在审批后增加出入库商品在库数
            // 增加出入库商品详情
            for (int i = 0; i < jsonArrayProducts.size(); i++) {

                JSONObject jsonObjectProduct = jsonArrayProducts.getJSONObject(i);
                PsiEnterLeaveStockDetail enterLeaveStockDetail = jsonObjectProduct.toJavaObject(PsiEnterLeaveStockDetail.class);

                CrmProduct crmProduct = CrmProduct.dao.findById(enterLeaveStockDetail.getProductId());
                if(ObjectUtil.isNull(crmProduct)) {
                    throw new YzcrmException("出入库失败，产品不存在");
                }
                if(PsiUtil.isEnterStock(crmEnum.getType()) && crmProduct.getUpcCodeUniqueFlag() == 1 && ObjectUtil.isEmpty(enterLeaveStockDetail.getUpcCode())) {
                    throw new YzcrmException("产品" + crmProduct.getName() + "的序列号不能为空");
                }


                enterLeaveStockDetail.setElsdetailId(null);
                enterLeaveStockDetail.setElsId(psiEnterLeaveStock.getElsId());
                enterLeaveStockDetail.setCreateTime(DateUtil.date());
                enterLeaveStockDetail.setCreateUserId(BaseUtil.getUser().getUserId());
                enterLeaveStockDetail.setUpdateTime(DateUtil.date());
                boolean result = enterLeaveStockDetail.save();
                if(!result) {
                    throw new YzcrmException("产品详细保存失败");
                }
            }
        }

        return flag ? R.ok().put("data", Kv.by("els_id", psiEnterLeaveStock.getElsId())) : R.error();
    }

    /**
     * 获取场景 并 获取出入库列表
     * @param basePageRequest
     * @return
     */
    public R filterConditionAndGetPageList(BasePageRequest basePageRequest){

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Integer sceneId = jsonObject.getInteger("sceneId");
        JSONObject data = new JSONObject();
        if(sceneId != null && sceneId != 0){
            data = JSON.parseObject(AdminScene.dao.findById(sceneId).getData());
        }
        if(sceneId == null && jsonObject.getInteger("type") == 1){
            data = new JSONObject().fluentPut("is_transform", new JSONObject().fluentPut("name", "is_transform").fluentPut("condition", "is").fluentPut("value", "0"));
        }
        if(jsonObject.getJSONObject("data") != null){
            if(data != null){
                data.putAll(jsonObject.getJSONObject("data"));
            }
        }
        jsonObject.put("data",data);
        basePageRequest.setJsonObject(jsonObject);
        return getEnterLeaveStockPageList(basePageRequest);
    }

    /**
     * 获取出入库列表
     * @param basePageRequest
     * @return
     */
    public R getEnterLeaveStockPageList(BasePageRequest basePageRequest) {

        JSONObject jsonObject = basePageRequest.getJsonObject();
        Kv kv = new Kv();
        List<JSONObject> queryList = new ArrayList<>();
        Integer type = jsonObject.getInteger("type");
        boolean isValid = jsonObject.getBoolean("isValid") != null ? jsonObject.getBoolean("isValid") : false;

        //自定义字段列表
        Map<String, AdminField> fieldMap = adminSceneService.getAdminFieldMap(type);

        // 取得场景名称 同label
        String realm = CrmEnum.parse(type).getName();
        if(ObjectUtil.isNull(realm)) {
            return R.error("type不符合要求");
        }

        // 附加检索条件
        JSONObject data = basePageRequest.getJsonObject().getJSONObject("data");
        if (!adminSceneService.appendSqlCondition(kv, fieldMap, queryList, data, type)){
            return R.error("参数包含非法字段");
        }
        String search = basePageRequest.getJsonObject().getString("search");
        if(StrUtil.isNotEmpty(search)){
            if (!adminSceneService.appendSqlSearch(type, queryList, search)){
                return R.error("参数包含非法字段");
            }
            if(!kv.containsKey("fixed")){
                kv.set("fixed",true);
            }
        }

        // 获取排序字段
        String camelField = basePageRequest.getJsonObject().getString("sortField");
        String sortField = StrUtil.toUnderlineCase(camelField);
        String orderNum = basePageRequest.getJsonObject().getString("order");
        if(StrUtil.isEmpty(sortField) || StrUtil.isEmpty(orderNum)){
            kv.set("orderByKey", "update_time").set("orderByType", "desc").set("fieldType", 1);
        }else{
            if(! ParamsUtil.isValid(sortField)){
                return R.error("参数包含非法字段");
            }
            orderNum = "2".equals(orderNum) ? "asc" : "desc";
            kv.set("orderByKey", sortField).set("orderByType", orderNum).set("fieldType", fieldMap.get(sortField) != null ? fieldMap.get(sortField).getFieldType() : 0);
        }

        // 开始生成条件SQL
        StringBuilder conditions = new StringBuilder();

        //获取已审核数据
        if(isValid) {
            conditions.append(" and check_status = 1");
        }

        conditions.append(" and status != 2 ");
        conditions.append(" and label =  " + type);

        // 检索权限
        Long userId = BaseUtil.getUserId();
        List<Integer> roles = BaseUtil.getUser().getRoles();
        if(! BaseConstant.SUPER_ADMIN_USER_ID.equals(userId) && !roles.contains(BaseConstant.SUPER_ADMIN_ROLE_ID)){

            String menuRealm = "";
            if(type == CrmEnum.PSI_SALES_ENTER.getType() ) {
                menuRealm = "salesEnter";
            } else if(type == CrmEnum.PSI_RETRUN_ENTER.getType() ) {
                menuRealm = "retrunEnter";
            } else if(type == CrmEnum.PSI_REPAIR_ENTER.getType() ) {
                menuRealm = "repairEnter";
            } else if(type == CrmEnum.PSI_TEST_ENTER.getType() ) {
                menuRealm = "testEnter";
            } else if(type == CrmEnum.PSI_INVENTORY_PROFIT_ENTER.getType() ) {
                menuRealm = "inventoryProfitEnter";
            } else if(type == CrmEnum.PSI_OTHER_ENTER.getType() ) {
                menuRealm = "otherEnter";
            } else if(type == CrmEnum.PSI_PURCHASE_ENTER.getType() ) {
                menuRealm = "purchaseEnter";
            } else if(type == CrmEnum.PSI_SALES_LEAVE.getType() ) {
                menuRealm = "salesLeave";
            } else if(type == CrmEnum.PSI_BORROW_LEAVE.getType() ) {
                menuRealm = "borrowLeave";
            } else if(type == CrmEnum.PSI_REPAIR_LEAVE.getType() ) {
                menuRealm = "repairLeave";
            } else if(type == CrmEnum.PSI_TEST_LEAVE.getType() ) {
                menuRealm = "testLeave";
            } else if(type == CrmEnum.PSI_INVENTORY_LOSS_LEAVE.getType() ) {
                menuRealm = "inventoryLossLeave";
            } else if(type == CrmEnum.PSI_OTHER_LEAVE.getType() ) {
                menuRealm = "otherLeave";
            }

            List<Long> longs = Aop.get(AdminUserService.class).queryUserByAuth(userId, menuRealm);
            if(longs != null && longs.size() > 0){
                conditions.append(" and (a.owner_user_id in (").append(StrUtil.join(",", longs)).append(")");
                conditions.append(")");
            }
        }
        JSONObject sqlObject = new JSONObject();
        sqlObject.put("sql", conditions.toString());
        sqlObject.put("type", 1);
        if(!kv.containsKey("fixed")){
            kv.set("fixed",true);
        }
        queryList.add(sqlObject);

        // 设置分页
        if(StrUtil.isEmpty(basePageRequest.getJsonObject().getString("excel"))){
            kv.set("page", (basePageRequest.getPage() - 1) * basePageRequest.getLimit()).set("limit", basePageRequest.getLimit());
        }

        String selectSql = "select * ";
        List<String> batchList = adminSceneService.queryBatchId(queryList);
        if(batchList.size()==0&&kv.containsKey("field")){
            batchList.add("");
        }
        kv.set("select", selectSql).set("queryList", queryList).set("realm", realm).set("fieldMap", fieldMap).set("label", type);
        kv.set("batchList",batchList);
        SqlPara sqlPara = null;
        if(kv.getInt("fieldType") == 0){
            sqlPara = Db.getSqlPara("psi.enterLeaveStock.queryEnterLeaveStockPageList2", kv);
        }else{
            sqlPara = Db.getSqlPara("psi.enterLeaveStock.queryEnterLeaveStockPageList1", kv);
        }

        // 检索数据
        List<Record> recordPage = Db.find(sqlPara);
        
        // 检索出入库明细
        recordPage.forEach(record -> {

            Integer elsId = record.get("elsId");
            List<PsiEnterLeaveStockDetail> listPsiEnterLeaveStockDetail = PsiEnterLeaveStockDetail.dao.find(Db.getSql("psi.enterLeaveStockDetail.queryByElsId"), elsId);
            record.set("listProductDetail", listPsiEnterLeaveStockDetail);

        });

        JSONObject resultJsonObject = new JSONObject();
        resultJsonObject.put("list", recordPage);
        SqlPara countSql = Db.getSqlPara("psi.enterLeaveStock.queryPsiEnterLeaveStockPageListCount", kv);
        Integer count = Db.queryInt(countSql.getSql(), countSql.getPara());
        resultJsonObject.put("totalRow", count);
        return R.ok().put("data", resultJsonObject);

    }

    /**
     * @author wyq
     * 根据出入库id查询
     */
    public Record queryById(Integer elsId){
        Record record = Db.findFirst(Db.getSql("psi.enterLeaveStock.queryById"), elsId);
        List<Record> recordList = Db.find("select name,value from `yzcrm_admin_fieldv` where batch_id = ?", record.getStr("batch_id"));
        recordList.forEach(field -> record.set(field.getStr("name"), field.getStr("value")));
        return record;
    }

    /**
     * @author lg
     * 查询编辑字段
     */
    public List<Record> queryField(Integer elsId, Integer label){

        // 获取label
        CrmEnum crmEnum = CrmEnum.parse(label);

        Record enterLeaveStock = queryById(elsId);
        List<Record> fieldList = adminFieldService.queryUpdateField(crmEnum.getType(), enterLeaveStock);

        if(!PsiUtil.isEnterStock(label) && CrmEnum.PSI_INVENTORY_LOSS_LEAVE.getType() != label) {

            fieldList.add(new Record().set("fieldName", "map_address")
                    .set("name", "地区定位")
                    .set("value", Kv.by("location", enterLeaveStock.getStr("location"))
                            .set("address", enterLeaveStock.getStr("address"))
                            .set("detailAddress", enterLeaveStock.getStr("detail_address"))
                            .set("lng", enterLeaveStock.getStr("lng"))
                            .set("lat", enterLeaveStock.getStr("lat")))
                    .set("formType", "map_address")
                    .set("isNull", 0));
        }

        return fieldList;
    }

    /**
     * @author wyq
     * 根据id删除出入库(审批通过的也可以删除)
     */
    @Before(TxSerializable.class)
    public R deleteByIds(String elsIds){

        String[] idsArr = elsIds.split(",");
        List<Record> idsList = new ArrayList<>();
        for(String id : idsArr){
            if(!BaseUtil.getUserId().equals(BaseConstant.SUPER_ADMIN_USER_ID) && !BaseUtil.getUser().getRoles().contains(BaseConstant.SUPER_ADMIN_ROLE_ID)){
                // TODO 测试时需要确认表是否加ro_user_id和rw_user_id && Db.queryInt(Db.getSql("crm.customer.queryIsRoUser"), BaseUtil.getUserId(), id) > 0
                return R.error("没有权限");
            }
            Record record = new Record();
            idsList.add(record.set("els_id", Integer.valueOf(id)));
        }

        List<Record> batchIdList = Db.find(Db.getSqlPara("psi.enterLeaveStock.queryBatchIdByIds", Kv.by("ids", idsArr)));
        return Db.tx(() -> {
            Db.batch(Db.getSql("psi.enterLeaveStock.deleteByIds"), "els_id", idsList, 100);
//            Db.batch("delete from yzcrm_admin_fieldv where batch_id = ?", "batch_id", batchIdList, 100);

            // 删除明细和在库
            for (int i = 0; i < idsList.size(); i++) {

                Record record = idsList.get(i);
                Integer elsId = record.get("els_id");

                // 刪除出入库记录，在库数量做相反处理
                this.deleteStockpileByElsId(elsId);

                // 刪除明细
                Db.update(Db.getSql("psi.enterLeaveStockDetail.deleteByElsId"), elsId);

            }

            return true;
        }) ? R.ok() : R.error();
    }

    /**
     * @author wyq
     * 基本信息
     */
    public List<Record> information(Integer label, Integer elsId) {
        Record record = queryById(elsId);
        List<String> keyList = null;

        if(PsiUtil.isEnterStock(label)) {

            // 入库
            keyList = Arrays.asList("remarks", "els_num", "link_id", "els_user_id", "els_date", "object_id", "storehouse_id"
                    ,"customer_name_receiver","customer_contact_receiver","customer_phone_receiver");

        } else {

            //出库
            keyList = Arrays.asList("remarks", "els_num", "link_id", "els_user_id", "els_date", "object_id", "storehouse_id"
            ,"customer_name_receiver","customer_contact_receiver","customer_phone_receiver","express_name","express_num","confirming_user_id");

        }


        CrmEnum crmEnum = CrmEnum.parse(label);
        List<Record> recordList = adminFieldService.queryInformation(crmEnum, record, keyList);

        if(!PsiUtil.isEnterStock(label) && CrmEnum.PSI_INVENTORY_LOSS_LEAVE.getType() != label) {

            recordList.add(new Record().set("name","地区定位").set("value",Kv.by("location", record.getStr("location"))
                    .set("address", record.getStr("address"))
                    .set("detailAddress", record.getStr("detail_address"))
                    .set("lng", record.getStr("lng"))
                    .set("lat", record.getStr("lat"))).set("formType","map_address").set("field_type",1));

        }

//        recordList.add(new Record().set("name","仓库名称").set("value",new Record().set("storehouseId",record.getInt("storehouse_id")).set("storehouseName",record.getStr("storehouse_name"))).set("formType","storehouse").set("field_type",1));

        return recordList.stream().sorted(Comparator.comparingInt(r->-r.getInt("field_type"))).map(r-> r.remove("field_type","field_name","setting","type")).collect(Collectors.toList());
    }

    /**
     * 根据出入库ID获取出入库明细
     * @param elsId
     * @return
     */
    public List<Record> listEnterLeaveStockDetailByElsId(Integer elsId) {

        // 检索出入库详细信息
        List<Record> listPsiEnterLeaveStockDetail = Db.find(Db.getSql("psi.enterLeaveStockDetail.queryByElsId"), elsId);

        return listPsiEnterLeaveStockDetail;
    }


    /**
     * 出入库审批通过，更新在库
     * @param elsId
     */
    public String updateStockpileByElsId(Integer elsId) {

        String msgStockpileWarning = "";

        // 检索出入库信息
        PsiEnterLeaveStock psiEnterLeaveStock = PsiEnterLeaveStock.dao.findFirst(Db.getSql("psi.enterLeaveStock.queryById"), elsId);
        if (ObjectUtil.isNull(psiEnterLeaveStock)) {

            throw new YzcrmException("出入库信息不存在");
        }

        // 出入库标记
        boolean isEnter = PsiUtil.isEnterStock(psiEnterLeaveStock.getLabel());

        // 检索出入库详细信息
        List<PsiEnterLeaveStockDetail> listPsiEnterLeaveStockDetail = PsiEnterLeaveStockDetail.dao.find(Db.getSql("psi.enterLeaveStockDetail.queryByElsId"), elsId);
        for (int i = 0; i < listPsiEnterLeaveStockDetail.size(); i++) {

            PsiEnterLeaveStockDetail psiEnterLeaveStockDetail = listPsiEnterLeaveStockDetail.get(i);

            // 获取在库商品信息
            PsiStockpile psiStockpile = PsiStockpile.dao.findFirst(Db.getSql("psi.stockpile.queryStockpileByStockpileId"), psiEnterLeaveStockDetail.getStockpileId());


            // 判断出库或者入库
            if (isEnter) {
                // 入库

                // 入库直接加数量，
                psiStockpile.setQuantity(psiStockpile.getQuantity() + psiEnterLeaveStockDetail.getElsQuantity()); // 在库增加
                psiStockpile.update();
                psiEnterLeaveStockDetail.setBalance(psiStockpile.getQuantity()); // 现在库记录


                // 如果是采购入库，增加供应商和产品关联关系
                if (psiEnterLeaveStock.getCheckStatus() == CrmEnum.PSI_PURCHASE_ENTER.getType()) {


                    // 判断供应商产品是已存在，不存在即增加关系
                    List<Record> recordList = Db.find(Db.getSql("psi.productSupplier:queryByProductIdSupplierId"), psiEnterLeaveStock.getSupplierId(), psiEnterLeaveStockDetail.getProductId());
                    if (ObjectUtil.isNull(recordList) || recordList.size() <= 0) {
                        PsiProductSupplier productSupplier = new PsiProductSupplier();
                        productSupplier.setProductId(psiEnterLeaveStockDetail.getProductId());
                        productSupplier.setSupplierId(psiEnterLeaveStock.getSupplierId());
                        productSupplier.save();
                    }

                }

                // 判断预警库存，提示给用户。0不提示
                if(psiStockpile.getMaxnumWarn() != 0 &&
                        psiStockpile.getMaxnumWarn() <= psiStockpile.getQuantity()) {

                    msgStockpileWarning =  "入库成功。警告：产品在库数高于预警值"+psiStockpile.getMaxnumWarn()+"。仓库："+psiEnterLeaveStockDetail.getStorehouseName()+
                            "。产品："+psiEnterLeaveStockDetail.getProductName()+
                            "，编号"+psiEnterLeaveStockDetail.getProductNum()+"，规格"+psiEnterLeaveStockDetail.getProductSpecName()+"。 ";
                }


            } else {
                // 出库

                // 出库要判断在库数量是否足够
                if(psiStockpile.getQuantity() - psiEnterLeaveStockDetail.getElsQuantity() < 0) {

                    throw new YzcrmException("在库数量不足，无法出库");
                }

                psiStockpile.setQuantity(psiStockpile.getQuantity() - psiEnterLeaveStockDetail.getElsQuantity()); // 在库减少
                psiStockpile.update();
                psiEnterLeaveStockDetail.setBalance(psiStockpile.getQuantity()); // 现在库

                // 判断预警库存，提示给用户。0不提示
                if(psiStockpile.getMinnumWarn() != 0 &&
                        psiStockpile.getMinnumWarn() >= psiStockpile.getQuantity()) {

                    msgStockpileWarning =  "出库成功。警告：产品在库数低于预警值"+psiStockpile.getMinnumWarn()+"。仓库："+psiEnterLeaveStockDetail.getStorehouseName()+
                            "。产品："+psiEnterLeaveStockDetail.getProductName()+
                            "，编号"+psiEnterLeaveStockDetail.getProductNum()+"，规格"+psiEnterLeaveStockDetail.getProductSpecName()+"。 ";
                }

            }
        }

        return msgStockpileWarning;
    }

    /**
     * 刪除出入库记录，在库数量做相反处理
     * @param elsId
     */
    private void deleteStockpileByElsId(Integer elsId) {

        boolean result = false;
        // 检索出入库信息
        PsiEnterLeaveStock psiEnterLeaveStock = PsiEnterLeaveStock.dao.findFirst(Db.getSql("psi.enterLeaveStock.queryById"), elsId);
        if (ObjectUtil.isNull(psiEnterLeaveStock)) {

            throw new YzcrmException("出入库信息不存在");
        }

        // 出入库标记
        boolean isEnter = PsiUtil.isEnterStock(psiEnterLeaveStock.getLabel());

        // 检索出入库详细信息
        List<PsiEnterLeaveStockDetail> listPsiEnterLeaveStockDetail = PsiEnterLeaveStockDetail.dao.find(Db.getSql("psi.enterLeaveStockDetail.queryByElsId"), elsId);
        for (int i = 0; i < listPsiEnterLeaveStockDetail.size(); i++) {

            PsiEnterLeaveStockDetail psiEnterLeaveStockDetail = listPsiEnterLeaveStockDetail.get(i);

            // 获取在库商品信息
            PsiStockpile psiStockpile = PsiStockpile.dao.findFirst(Db.getSql("psi.stockpile.queryStockpileByStockpileId"), psiEnterLeaveStockDetail.getStockpileId());

            // 判断出库或者入库
            if (isEnter) {
                // 入库

                // 入库数量减少
                psiStockpile.setQuantity(psiStockpile.getQuantity() - psiEnterLeaveStockDetail.getElsQuantity()); // 在库减少
                psiStockpile.update();
                psiEnterLeaveStockDetail.setBalance(psiStockpile.getQuantity()); // 现在库记录

            } else {
                // 出库

                psiStockpile.setQuantity(psiStockpile.getQuantity() + psiEnterLeaveStockDetail.getElsQuantity()); // 在库增加
                psiStockpile.update();
                psiEnterLeaveStockDetail.setBalance(psiStockpile.getQuantity()); // 现在库

            }
        }

    }

    /**
     * 最后一次审核，更新快递及出库产品序列号
     * @param jsonObject
     * @return
     */
    public R updateLeaveStockInfo(JSONObject jsonObject) {

        PsiEnterLeaveStock psiEnterLeaveStock = jsonObject.getObject("entity", PsiEnterLeaveStock.class);
        if(ObjectUtil.isNull(psiEnterLeaveStock)) {
            throw new YzcrmException("参数不正确");
        }

        JSONArray jsonArrayProducts = jsonObject.getJSONArray("products");

//        String batchId = StrUtil.isNotEmpty(psiEnterLeaveStock.getBatchId()) ? psiEnterLeaveStock.getBatchId() : IdUtil.simpleUUID();
//        adminFieldService.save(jsonObject.getJSONArray("field"), batchId);

        if(psiEnterLeaveStock.getElsId() != null){
            // 更新

//            crmRecordService.updateRecord(jsonObject.getJSONArray("field"), batchId);

            PsiEnterLeaveStock oldPsiEnterLeaveStock = PsiEnterLeaveStock.dao.findById(psiEnterLeaveStock.getElsId());
            if(ObjectUtil.isNull(oldPsiEnterLeaveStock)) {
                throw new YzcrmException("要修改的出入库信息不存在，无法编辑");
            }

            // 审核拒绝，已撤回，草稿的情况，不能够修改
            if(oldPsiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_REJECTED.getType()
                    || oldPsiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_UNDO.getType()
                    || oldPsiEnterLeaveStock.getCheckStatus() == CheckStatusEnum.CHECK_STATUS_DRAFT.getType()) {
                CheckStatusEnum checkStatusEnum = CheckStatusEnum.parse(oldPsiEnterLeaveStock.getCheckStatus());
                throw new YzcrmException("出入库信息"+checkStatusEnum.getRemarks()+"已撤回，无法审核");
            }

            // 更新物流信息
            oldPsiEnterLeaveStock.setExpressName(psiEnterLeaveStock.getExpressName());
            oldPsiEnterLeaveStock.setExpressNum(psiEnterLeaveStock.getExpressNum());
            oldPsiEnterLeaveStock.setUpdateTime(DateUtil.date());
            oldPsiEnterLeaveStock.setUpdateUserId(BaseUtil.getUser().getUserId());
            oldPsiEnterLeaveStock.update();

            // 在审批后设置序列号
            for (int i = 0; i < jsonArrayProducts.size(); i++) {

                JSONObject jsonObjectProduct = jsonArrayProducts.getJSONObject(i);
                PsiEnterLeaveStockDetail enterLeaveStockDetail = jsonObjectProduct.toJavaObject(PsiEnterLeaveStockDetail.class);

                PsiEnterLeaveStockDetail oldPsiEnterLeaveStockDetail = PsiEnterLeaveStockDetail.dao.findById(enterLeaveStockDetail.getElsdetailId());
                if(ObjectUtil.isNotNull(oldPsiEnterLeaveStockDetail)) {

                    CrmProduct product = CrmProduct.dao.findById(oldPsiEnterLeaveStockDetail.getProductId());
                    if(ObjectUtil.isNotNull(product)) {
                        // 判断必须输入序列号

                        if(product.getUpcCodeUniqueFlag() == 1 && ObjectUtil.isEmpty(enterLeaveStockDetail.getUpcCode())) {

                            throw new YzcrmException("请填写" + product.getName() + "的序列号");
                        }

                        oldPsiEnterLeaveStockDetail.setUpcCode(enterLeaveStockDetail.getUpcCode());
                        oldPsiEnterLeaveStockDetail.setUpdateTime(DateUtil.date());
                        oldPsiEnterLeaveStockDetail.setUpdateUserId(BaseUtil.getUser().getUserId());
                        oldPsiEnterLeaveStockDetail.update();
                    }
                } else {
                    throw new YzcrmException("审核的产品已被删除或改变，请刷新页面后重新偿试");
                }

            }
        }

        return R.ok().put("data", Kv.by("els_id", psiEnterLeaveStock.getElsId()));
    }


//    /**
//     * 检索出入库编号
//     * @param elsNum
//     * @param label
//     * @return
//     */
//    public R queryElsNum(String elsNum, Integer label) {
//
//        Kv kv = Kv.by("elsNum", elsNum).set("label", label);
//
//        // 获取入库
//        List<Record> records = Db.find(Db.getSqlPara("psi.enterLeaveStock", kv));
//
//        return R.ok().put("data", records);
//    }



}
